home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 28.9 KB | 1,026 lines | [TEXT/MPS ] |
- // UObject.cp
- // Copyright © 1984-1990 by Apple Computer, Inc. All rights reserved.
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __STDIO__
- #include <StdIo.h>
- #endif
-
- #ifndef __UOBJECT__
- #include <UObject.h>
- #endif
-
- #ifndef __ULIST__
- #include <UList.h>
- #endif
-
- #ifndef __UPATCH__
- #include <UPatch.h>
- #endif
-
- #ifndef __UMEMORY__
- #include <UMemory.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <Textedit.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UITERATOR__
- #include <UIterator.h>
- #endif
-
- #ifndef __UDEBUG__
- #include <UDebug.h>
- #endif
- #ifndef __UINSPECTOR__
- #include <UInspector.h>
- #endif
-
- #ifndef qMacApp
- #define qMacApp FALSE
- #endif
-
- //=====
- // case NOTE:
- // The optimizer redirects the following procedure names
- // We call the optimized names here since non-optimized dispatch
- // is not supported.
-
- // %_INITOBJ becomes %_OPTINITOBJ
- // %_INOBJ becomes %_OPTINOBJ
- // %_SETCLASSINDEX becomes %_OPTSETCI
- // %_METHOD becomes %_JMPTOTRAP
-
- //--------------------------------------------------------------------------------------------------
- // Typedef for void pascal procedures.
-
- typedef pascal void (*PascalProc)();
-
- //--------------------------------------------------------------------------------------------------
-
- const short kJTSkipOver = 2; // size of jmp (or loadseg) instruction that
- // must be skipped in the JT Entry in order
- // to get to the target address
- const char* kInvalidObj = "*Not an object*"; // return value from LookupObjName if not an object
-
- // SuperClassTable format
- typedef ObjClassID SuperClassTableSize; // in 32 B-E is a longint else int
-
- struct SuperClassTable
- {
- SuperClassTableSize itsSize;
- ObjClassID itsTable[1]; // Actually, a variable size array where each
- // entry's byte offset corresponds to its
- // ClassID and the entry's value is the
- // ClassID of the immediate superclass
- };
-
- typedef SuperClassTable* SuperClassTablePtr;
- typedef SuperClassTablePtr* SuperClassTableHandle;
-
- // ClassInfoProc format
- struct ClassInfoProc
- {
- ObjClassID itsClassID;
- short itsInstanceSize;
- MAName itsName;
- };
-
- typedef ClassInfoProc* ClassInfoProcPtr;
- typedef ClassInfoProcPtr* ClassInfoProcHandle;
-
- // ClassTable format
- typedef ObjClassID ClassTableSize; // in 32 B-E is a long else int
-
- #if qModelFarCode
- typedef Ptr ClassTableEntry; // Ptr to the JT Entry of the ClassInfoProc.
- // Add kJTSkipOver and you get a ClassInfoProcPtr.
- #else
- typedef short ClassTableEntry; // JT Offset of ClassInfoProc
- #endif
-
- typedef ClassTableEntry* ClassTableEntryPtr;
- typedef ClassTableEntryPtr* ClassTableEntryHandle;
-
- struct ClassTable
- {
- ClassTableSize itsSize;
- ClassTableEntry itsTable[1]; // Actually, a variable size array where
- // each entry's byte offset corresponds
- // to its ClassID and the entry's value
- // is used to locate its ClassInfoProc.
- };
- typedef ClassTable* ClassTablePtr;
- typedef ClassTablePtr* ClassTableHandle;
-
- typedef pascal void (* DoToClassType)(ObjClassID theClass, void* staticLink);
-
- class TNameOrderedClassIDs: public TSortedLongintList
- {
- public:
- pascal CompareResult TNameOrderedClassIDs::Compare(long item1, long item2); // override
- // Overridden to string compare the actual names of the classes
-
- pascal ObjClassID TNameOrderedClassIDs::ClassIDWithName(MAName keyStr);
- };
-
- //--------------------------------------------------------------------------------------------------
-
- ObjProcs gObjProcs;
-
- TNameOrderedClassIDs* pOrderedClassIds; // Classes ordered by name
- ObjClassID pTObjectClassID; // ClassID of the Root class
-
- Boolean pDisciplineMethodCalls; // Discipline method calls
- Boolean pDisciplineCoercions; // Discipline Coercions
- SuperClassTablePtr pSuperClassTable; // ptr to superclass table
- ClassTablePtr pClassTable; // ptr to superclass table
- pascal void (*pDispatchErrorProc)(); // Routine to handle dispatching failures
- pascal void (*pODFail)(TObject *); // address OD Failure Handler
- Boolean pAllocateObjectsFromPerm; // Used to track whether to allocate objects
- // from permanent memory or not.
- TObject* pCacheObj = NULL;
-
- //--------------------------------------------------------------------------------------------------
- // The following variables are initialized by a procedure called InitLinkerSymbols in UPascalObject.a.
- // They are copies of the address of corresponding symbols created by the linker. The linker symbols
- // begin with a '%_' instead of a 'g'. C++ identifiers cannot contain a '%'.
-
- Ptr gSuperClassTable; // Created by linker -Model Far and -opt
- Ptr gClassTable; // Created by linker for -Model Far and -opt
- Ptr gSelectorProcTable; // Created by linker for -Model Far and -opt
- Ptr gClassInfo; // Created by linker… except for -Model Far and -opt
-
- Ptr gJmpToTrapPatchPoint; // Location to patch in the MacApp dispatcher.
- Ptr gMethDispAddr; // Address of the MacApp dispatcher.
- Ptr gDisciplinedMethDispAddr; // Address of the disciplined MacApp dispatcher.
- Ptr gDisciplinedJmpToTrapPatchPoint; // Location to patch in the MacApp dispatcher to the
- // disciplined dispatching.
- //--------------------------------------------------------------------------------------------------
- // Procedures defined in UPascalObject.a for implementing optimized method dispatching.
-
- extern pascal void InitLinkerSymbols(void);
-
- //--------------------------------------------------------------------------------------------------
- // Some forward declarations.
-
- void InstallDispatcher(void);
- void OrderClassIdsByName(void);
- pascal void __ObjError(void);
-
- //--------------------------------------------------------------------------------------------------
- // An iterator for iterator over class ids.
-
- class CClassIterator: public CIterator
- {
- private:
- ObjClassID fCurrentID;
- ObjClassID fMaxID;
-
- public:
- CClassIterator(void);
-
- virtual Boolean More(void); // override
- // Returns TRUE if there are more elements to iterate over
-
- virtual void Reset(void); // override
- // Resets the iterator to begin again
-
- inline ObjClassID FirstClass(void);
- // returns the first window in the window list
-
- inline ObjClassID NextClass(void);
- // increments and then returns the current classID
-
- protected:
- virtual void Advance(void); // override
- // Advances the iteration
- };
-
- //--------------------------------------------------------------------------------------------------
-
- inline CClassIterator::CClassIterator()
- {
- fMaxID = pSuperClassTable->itsSize;
- fCurrentID = sizeof(ObjClassID);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- inline ObjClassID CClassIterator::FirstClass()
- {
- return sizeof(ObjClassID);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- inline ObjClassID CClassIterator::NextClass()
- {
- this->Advance();
- return fCurrentID;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- Boolean CClassIterator::More()
- {
- return (fCurrentID < fMaxID);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- void CClassIterator::Reset()
- {
- fCurrentID = this->FirstClass();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- void CClassIterator::Advance()
- {
- fCurrentID += sizeof(ObjClassID);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal CompareResult TestKey(long theClassID, MAName* keyStr)
- {
- MAName itemName;
-
- GetClassNameFromID((ObjClassID) theClassID, itemName);
- return RelString(*keyStr, itemName, FALSE, TRUE);
- }
-
- pascal ObjClassID TNameOrderedClassIDs::ClassIDWithName(MAName keyStr)
- {
- return (ObjClassID) Search((CompareLongType) TestKey, &keyStr);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // Overridden to string compare the actual names of the classes
-
- pascal CompareResult TNameOrderedClassIDs::Compare(long item1, long item2) // override
- {
- MAName item1Name, item2Name;
-
- GetClassNameFromID((ObjClassID) item1, item1Name);
- GetClassNameFromID((ObjClassID) item2, item2Name);
- return RelString(item1Name, item2Name, FALSE, TRUE);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Boolean AllocateObjectsFromPerm(Boolean allocateFromPerm)
- {
- Boolean previousState = pAllocateObjectsFromPerm;
- pAllocateObjectsFromPerm = allocateFromPerm;
- return previousState;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Boolean DisciplineMethodCalls(Boolean discipline)
- {
- Boolean previousState = pDisciplineMethodCalls;
- pDisciplineMethodCalls = discipline;
- return previousState;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void EachClassDo(DoToClassType DoToClass, void* staticLink)
- {
- // Manufacture classIDs for all classes from the root to the largest
-
- /* NOTE: Since maxID is obtained from the size of the super class table, maxID serves as a
- maximum bound on the possible range of class IDs. So, in the loop below, we only call DoToClass
- while aClassID is less than maxID. This is because the size (in bytes) of the
- super class table includes the bytes required to enter the size at the head of the
- super class table.
-
- Incidentally, since the class table follows the super class table, this gives us the
- following identity:
- superclass table ptr + size of super class table == class table ptr
-
- So, in 16-bit worlds, for a two class system, the superclass table could look like:
- 0x0006 0x0000 0x0002 <= super class table with class IDs 2 and 4, followed by
- 0x0006 0x4ADA 0x4ADC <= class table with offsets into jump table
- this structure gives us a maxID of 6 and the following while loop looks like:
-
- while ( aClassID < 6)…
- aClassID = aClassID + 2
- */
-
- CClassIterator iter;
-
- for (ObjClassID aClassID = iter.FirstClass(); iter.More(); aClassID = iter.NextClass())
- DoToClass(aClassID, staticLink);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void EachSubClassDo(ObjClassID testClass, DoToClassType DoToClass, void* staticLink)
- {
- CClassIterator iter;
-
- for (ObjClassID theClass = iter.FirstClass(); iter.More(); theClass = iter.NextClass())
- if (theClass != testClass && IsClassIDMemberClass(theClass, testClass))
- DoToClass(theClass, staticLink);
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void EachSuperClassDo(ObjClassID testClass, DoToClassType DoToClass, void* staticLink)
- {
- ObjClassID theSuperClass = GetSuperClassID(testClass);
- while (theSuperClass != kNilClass)
- {
- DoToClass(theSuperClass, staticLink);
- theSuperClass = GetSuperClassID(theSuperClass);
- }
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void FailNonObject(TObject* obj)
- {
- if (!IsObject(obj))
- {
- #if qDebugMsg
- VerboseIsObject(obj); // show why
- fprintf(stderr, "Object that failed discipline %p\n", obj);
- ProgramBreak("");
- #endif
- Failure(minErr, 0); // ??? need to assign a message
- }
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal TObject *FreeIfObject(TObject* obj)
- {
- if (obj)
- {
- #if qDebug
- if (!VerboseIsObject(obj))
- ProgramBreak("In FreeIfObject: Not handed a valid object.");
- #endif
- obj->Free();
- }
- return NULL;
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal ObjClassID GetClassID(TObject* obj)
- {
- #if qDebug
- FailNonObject(obj);
- #endif
- return **((ObjClassIDHandle) obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal ObjClassID GetClassIDFromName(const MAName& clName)
- {
- ObjClassID classID = pOrderedClassIds->ClassIDWithName(clName);
-
- #if qDebugMsg
- if (classID == kNilClass)
- {
- fprintf(stderr, "###GetClassIDFromName: Can't find class name %s\n", (char *) clName);
- if (gIntenseDebugging)
- ProgramBreak("");
- }
- #endif
-
- return classID;
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- ClassInfoProcHandle GetClassInfoProcHandle(ObjClassID classID)
- {
- // The following piece of code depends on Ptr being a (char *) and Handle being a (char **).
- // Remember C++ pointer arithmetic accounts for the size of the object pointed to!
-
- ClassInfoProcHandle aClassInfoProcHandle = (ClassInfoProcHandle)
- ((qModelFarCode ? 0 : GetA5())
- + *((ClassTableEntryPtr) ((Ptr) pClassTable + classID))
- + kJTSkipOver);
-
- return aClassInfoProcHandle;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void GetClassNameFromID(ObjClassID classID, MAName& clName)
- {
- const Str255 kClasInfoPrefix = "CLASINFO."; // 'CLASINFO.' prepended to class name
- ClassInfoProcHandle aClassInfoProcHandle;
- Ptr namePtr;
- short nameLength;
- Ptr clNamePtr;
- short i;
-
- if (classID == kNilClass || odd(classID))
- clName = kInvalidObj;
- else
- {
- aClassInfoProcHandle = GetClassInfoProcHandle(classID);
- namePtr = (Ptr) &(*aClassInfoProcHandle)->itsName;
-
- // discard = validMacsBugSymbol(namePtr, ord(namePtr) + 256, &clName);
- // delete(clName, 1, 9); // 'CLASINFO.'
- // !!! the above function call could conceivably return a null terminated pascal string
- // that would exceed a Str255 by one byte. If that happens we're HOSED. The workaround
- // is to have the validMacsBugSymbol call put the returned string on the stack with room
- // for that last null byte. The cost is yet another copy of the string on the stack. So…
- // anticipating that no identifier names will ever ACTUALLY be 255 chars we take the simple
- // path and return the name directly into the var parameter.
-
- // We need all the speed we can get here, so forego the use of validMacsBugSymbol
- // (it did make a difference) and do it ourselves. This routine would be a good
- // candidate for assembly
-
- if (*((unsigned char *) namePtr) == 0x80)
- {
- namePtr++;
- nameLength = *namePtr - kClasInfoPrefix.Length ();
- }
- else
- nameLength = (((*namePtr)) & 0x7F) - kClasInfoPrefix.Length();
- clName.Length() = (unsigned char) Min (kMANameSize, nameLength);
- clNamePtr = (Ptr) &clName[1];
- namePtr += kClasInfoPrefix.Length() + 1;
-
- // Be polite. Don't copy more bytes than the caller has reserved room for.
-
- int copyLen = (int) Min (clName.Length (), sizeof(MAName) - 1);
- for (i=1; i<=copyLen; i++)
- *clNamePtr++ = *namePtr++;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Size GetClassSizeFromID(ObjClassID classID)
- {
- return (*GetClassInfoProcHandle(classID))->itsInstanceSize;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal ObjClassID GetSuperClassID(ObjClassID objID)
- {
- if (objID != kNilClass)
- return *((ObjClassIDPtr) ((Ptr) pSuperClassTable + objID));
- else
- return kNilClass;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- SuperClassTablePtr GetSuperClassTablePtr(void)
- {
- if (qModelFarCode)
- return (SuperClassTablePtr) gSuperClassTable;
- else
- return (SuperClassTablePtr) gClassInfo;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- ClassTablePtr GetClassTablePtr(void)
- {
- if (qModelFarCode)
- return (ClassTablePtr) gClassTable;
- else
- // Old style. Table is past end of superclass table
- return (ClassTablePtr) ((Ptr) GetSuperClassTablePtr() + GetSuperClassTablePtr()->itsSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- Ptr GetSelectorProcTablePtr(void)
- {
- if (qModelFarCode)
- return gSelectorProcTable;
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- pascal void InitUObject(void)
- {
- InitLinkerSymbols();
-
- if (qDebug)
- pDisciplineMethodCalls = FALSE;
-
- if (qInspector)
- AddNewObjectsToInspector(FALSE);
-
- pDisciplineCoercions = FALSE; // so run time coercions are not checked
-
- pAllocateObjectsFromPerm = TRUE;
-
- InstallDispatcher();
-
- SetStdObjProcs(gObjProcs);
-
- pTObjectClassID = (ObjClassID) sizeof(ObjClassID);
-
- #ifdef Comment
- {
- ofstream out ("ClassInfo.unordered");
- CClassIterator iter;
-
- for (ObjClassID theClass = iter.FirstClass(); iter.More(); theClass = iter.NextClass())
- {
- ClassInfoProc& aClassInfoProc = **GetClassInfoProcHandle(theClass);
-
- out << "Class Name: " << aClassInfoProc.itsName << "\n";
- out << " ID: " << aClassInfoProc.itsClassID << "\n";
- out << " Size: " << aClassInfoProc.itsInstanceSize << "\n";
- out << "\n";
- }
- out.close();
- }
- #endif
-
- OrderClassIdsByName();
-
- if (qRangeCheck)
- pDisciplineCoercions = TRUE;
-
- if (qInspector)
- AddNewObjectsToInspector(TRUE);
-
- if (qDebug)
- pDisciplineMethodCalls = TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Boolean IsObject(TObject *obj)
- {
- return gObjProcs.IsObjectProc(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Boolean ObjIsObjectProc(TObject *obj)
- {
- // Test for handle not purged since we don't allow purgeable objects (??? yet?, ever?)
- // Test objecthood
-
- if (IsHandle((Handle) obj) &&
- (*Handle(obj)) &&
- IsClassIDMemberClass(**((ObjClassIDHandle) obj), pTObjectClassID) &&
- GetHandleSize(Handle(obj)) >= GetClassSizeFromID(**((ObjClassIDHandle) obj)))
- return TRUE;
- else
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal Boolean IsMemberClassID(TObject *obj, ObjClassID objID)
- {
- #if qDebug
- FailNonObject(obj);
-
- if (!IsObject(obj))
- return FALSE;
- #endif
-
- return IsClassIDMemberClass(**((ObjClassIDHandle) obj), objID);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- // makes objects for "new" calls. Internal use only.
- pascal TObject *MakeNewInstance(ObjClassID classID)
- {
- TObject* returnObj = gObjProcs.AllocateProc(classID);
-
- FailNIL(returnObj);
- return returnObj;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- // makes objects for "new" calls. Internal use only.
-
- pascal TObject *ObjAllocateProc(ObjClassID classID)
- {
- const unsigned char initVal = 0xF1; // guaranteed to be odd at all byte boundaries
- TObject *obj;
-
- if (classID != kNilClass)
- {
- Size itsSize = GetClassSizeFromID(classID);
- if ((pCacheObj) && !IsHandlePurged(Handle(pCacheObj)) &&
- GetHandleSize(Handle(pCacheObj)) >= itsSize)
- {
- obj = pCacheObj;
- SetHandleSize(Handle(pCacheObj), itsSize);
- HNoPurge(Handle(pCacheObj));
- pCacheObj = NULL;
- }
- else
- {
- if (qMacApp && pAllocateObjectsFromPerm)
- obj = (TObject *) NewPermHandle(itsSize);
- else
- obj = (TObject *) NewHandle(itsSize);
- }
-
- if (obj)
- {
- if (qDebug)
- BlockSet(*((Handle) obj), itsSize, initVal);
-
- // Install class ID into object
- **((ObjClassIDHandle) obj) = classID;
- }
- }
- else
- obj = NULL;
-
- if (qInspector)
- AddObjectToInspector(obj);
-
- return obj;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal TObject *NewObjectByClassId(ObjClassID classID)
- {
- #if qDebugMsg
- if (gAskAboutAlloc && CanReadLn())
- {
- MAName caller;
- MAName className;
-
- GetCallersMethodName(caller);
- GetClassNameFromID(classID, className);
- fprintf(stderr, "Within %s, trying to make a '%s'.\n", (char *) caller, (char *) className);
-
- if (ReadYesNo(" Return NULL (Y or N) [N]? "))
- return NULL;
- }
- #endif
-
- return MakeNewInstance(classID);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal TObject *NewObjectByClassName(const MAName& className)
- {
- #if qDebugMsg
- if (gAskAboutAlloc && CanReadLn())
- {
- MAName s;
-
- GetCallersMethodName(s);
- fprintf(stderr, "Within %s, trying to make a '%s'.\n", (char *) s, (char *) className);
-
- if (ReadYesNo(" Return NULL (Y or N) [N]? "))
- return NULL;
- }
- #endif
-
- ObjClassID classID = GetClassIDFromName(className);
- if (classID != kNilClass)
- return MakeNewInstance(classID);
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- #if qDebugMsg
- pascal void OBJFail(short error)
- #else
- pascal void OBJFail(short)
- #endif
- {
- #if qDebugMsg
- switch (error)
- {
- case kFailCoercion:
- ProgramBreak("Object type coercion error.");
- break;
- case kFailMethNotFound:
- ProgramBreak("Method not found");
- break;
- default:
- fprintf(stderr, "Failure code: %d\n", error);
- ProgramBreak("Object runtime failure. See UObject.p.");
- break;
- }
- #endif
- #if qMacApp
- Failure(minErr, 0); // ??? need to assign a message
- #else
- // ??? Should we do anything if not for MacApp?
- #endif
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- void OrderClassIdsByName(void)
- {
- CClassIterator iter;
- pOrderedClassIds = new TNameOrderedClassIDs;
- pOrderedClassIds->ISortedLongintList();
-
- for (ObjClassID theClass = iter.FirstClass(); iter.More(); theClass = iter.NextClass())
- if (pClassTable->itsTable[theClass / sizeof(ObjClassID)] != 0)
- pOrderedClassIds->Insert((long) theClass);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MADebug
-
- pascal Boolean VerboseIsObject(TObject *obj)
-
- {
- MAName className;
- Size classSize;
- Size instSize;
-
-
- // Test for handle not purged since we don't allow purgeable objects (??? yet?, ever?)
-
- if (VerboseIsHandle((Handle) obj))
- {
- if (*((Handle) obj) == NULL)
- fprintf(stderr, " That handle appears to be purged.\n");
- else if (!IsClassIDMemberClass(**((ObjClassIDHandle) obj), pTObjectClassID))
- fprintf(stderr, " That handle is not a subclass of TObject.\n");
- else if (GetHandleSize((Handle) obj) < GetClassSizeFromID(GetClassID(obj)))
- {
- GetClassNameFromID(GetClassID(obj), className);
- classSize = GetClassSizeFromID(GetClassID(obj));
- instSize = GetHandleSize((Handle) obj);
- fprintf(stderr, " That handle at: %ld bytes is smaller than a %s is supposed to be at: %ld bytes.\n",
- instSize, (char *) className, classSize);
- }
- else
- return TRUE;
- }
-
- return TRUE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment %MAInit
-
- // LOW LEVEL one time initialization. Must be in same segment as dispatcher.
-
- void InstallDispatcher(void)
- {
- struct JmpToTrapPatch {
- short Jmp; // jmp instruction
- PascalProc Routine; // address to jump to
- };
- typedef JmpToTrapPatch *JmpToTrapPatchPtr;
-
- JmpToTrapPatchPtr aJmpToTrapPatchPtr;
-
-
- /* The new method dispatcher provided with MacApp is enough faster that it is even worth using
- instead of the ROM based dispatcher. */
-
- #if qDebug
- pODFail = &FailNonObject;
- #endif
-
- /* NOTE =================================================
- the following is a real slimedog trick but since we are
- after performance in this bottleneck we'll do it anyway.
- since it saves a memory fetch for each dispatch.
- Don't need to flush the cache here.
- */
- aJmpToTrapPatchPtr = (JmpToTrapPatch *) gJmpToTrapPatchPoint;
- aJmpToTrapPatchPtr->Jmp = 0x4EF9;
- #if qDebug
- aJmpToTrapPatchPtr->Routine = (PascalProc) gDisciplinedMethDispAddr;
- #else
- aJmpToTrapPatchPtr->Routine = (PascalProc) gMethDispAddr;
- #endif
-
- #if qDebug
- aJmpToTrapPatchPtr = (JmpToTrapPatchPtr) gDisciplinedJmpToTrapPatchPoint;
- aJmpToTrapPatchPtr->Jmp = 0x4EF9; // JMP #Routine
- aJmpToTrapPatchPtr->Routine = (PascalProc) gMethDispAddr;
- #endif
-
- // Don't forget the class and superclass tables and the error handler
-
- pSuperClassTable = GetSuperClassTablePtr();
- pClassTable = GetClassTablePtr();
- // if (GetSelectorProcTablePtr()); /*!!! suppress dead strip of table. Fix b4 final */
- pDispatchErrorProc = &__ObjError;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- /* LOW LEVEL routine called at run time verify object coercions. It returns its obj
- parameter if the parameter is nil or passes the membership test. Otherwise it calls
- ObjFail. */
-
- pascal TObject *__OBCHK(TObject *obj, Ptr jumpTablePtr)
- {
- if (pDisciplineCoercions)
- {
- #if qDebug
- if (obj)
- FailNonObject(obj);
- #endif
- if ((obj) && !IsClassIDMemberClass(**((ObjClassIDHandle) obj),
- **((ObjClassIDHandle) jumpTablePtr)))
- OBJFail(kFailCoercion);
- }
-
- return obj;
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- /* LOW LEVEL routine called by DISPOSE(<object>).
- Forwards to the dispose bottleneck. */
-
- pascal void __OBDISP(TObject *obj)
- {
- gObjProcs.DisposeProc(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- // Default LOW LEVEL proc used in Dispose object bottleneck
-
- pascal void ObjDisposeProc(TObject *obj)
- {
- #if qDebug
- FailNonObject(obj);
- #endif
-
- if (qInspector)
- RemoveObjectFromInspector(obj);
-
- if ((pCacheObj) &&
- !IsHandlePurged((Handle) pCacheObj) &&
- GetHandleSize((Handle) pCacheObj) >= GetHandleSize((Handle) obj))
- { // cached one is better
- obj = (TObject *) DisposeIfHandle((Handle) obj);
- }
- else
- { // new one is better
- if (pCacheObj)
- pCacheObj = (TObject *) DisposeIfHandle((Handle) pCacheObj);
-
- pCacheObj = obj;
- HPurge((Handle) pCacheObj);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- pascal void SetStdObjProcs(ObjProcs& theObjProcs)
- {
- theObjProcs.AllocateProc = ObjAllocateProc;
- theObjProcs.DisposeProc = ObjDisposeProc;
- theObjProcs.IsObjectProc = ObjIsObjectProc;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- /* LOW LEVEL Error routine that ROM method dispatch routine jumps to if method not found
- Address of this routine is stuffed at lomem location MAErrProc at startup */
-
- pascal void __ObjError(void)
- {
- OBJFail(kFailMethNotFound); // Method Not Found
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- // LOW LEVEL routine called by NEW(<object>);
-
- pascal void __OBNEW(TObject*& obj, Ptr jumpTablePtr, short)
- {
- ObjClassID classID = (*((ClassInfoProcHandle) jumpTablePtr))->itsClassID;
-
- #if qDebugMsg
- if (gAskAboutAlloc && CanReadLn())
- {
- MAName caller;
- MAName className;
-
- GetCallersMethodName(caller);
- GetClassNameFromID(classID, className);
- fprintf(stderr, "Within %s, trying to make a '%s'.\n", (char *) caller, (char *) className);
- if (ReadYesNo(" Return NULL (Y or N) [N]? "))
- {
- obj = NULL;
- return;
- }
- }
- #endif
-
- obj = NULL; // in case failure is signalled
- obj = MakeNewInstance(classID);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAObjectRes
-
- // LOW LEVEL called to perform MEMBER function
-
- pascal Boolean __OPTINOBJ(TObject *obj, Ptr jumpTablePtr)
- {
- #if qDebug
- if (obj)
- FailNonObject(obj);
- #endif
- return (obj) && IsClassIDMemberClass(**((ObjClassIDHandle) obj),
- (*((ClassInfoProcHandle) jumpTablePtr))->itsClassID);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // Must actually be in "Main" since it is called in UNIT setup by Pascal */
-
- #pragma segment Main
-
- /* LOW LEVEL The Pascal compiler generates code to call this procedure automatically, before
- initializing the units and starting the application"s main program. This function must always
- work on 64K ROMs. */
-
- pascal void __PGM1(void)
- {
- }
-